import asyncio
import json
import logging
import os
from pathlib import Path
from typing import List

import pytz
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import TextContent, Tool

from .core import TimeMaster

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialize TimeMaster
timemaster = TimeMaster()
logger.info(f"TimeMaster initialized, online mode: {timemaster._is_online}")

# Create MCP server
server = Server("TimeMaster")


@server.list_tools()
async def list_tools() -> List[Tool]:
    """List available tools."""
    return [
        Tool(
            name="get_time",
            description="Unified time interface - get current time or convert existing time between timezones",
            inputSchema={
                "type": "object",
                "properties": {
                    "timezone": {
                        "type": "string",
                        "description": "Target timezone (default: local timezone)",
                    },
                    "time_str": {
                        "type": "string",
                        "description": "Time string to convert (if not provided, gets current time)",
                    },
                    "from_tz": {
                        "type": "string",
                        "description": "Source timezone for conversion (required if time_str is provided)",
                    },
                    "format": {
                        "type": "string",
                        "description": "Output format: 'iso' or 'friendly_cn' (default: 'iso')",
                        "default": "iso",
                    },
                },
            },
        ),
        Tool(
            name="get_local_timezone",
            description="Get the local system timezone",
            inputSchema={"type": "object", "properties": {}},
        ),
        Tool(
            name="search_timezones",
            description="Search for timezones matching a query. Use empty string to list all timezones.",
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Search query for timezone names (empty string returns all timezones)",
                        "default": "",
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Maximum number of results to return (default: 20)",
                        "default": 20,
                    },
                },
            },
        ),
        Tool(
            name="calculate_time_difference",
            description=(
                "Calculate the time difference between two times "
                "in different timezones"
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "time1": {
                        "type": "string",
                        "description": "First time string",
                    },
                    "tz1": {
                        "type": "string",
                        "description": "Timezone for first time",
                    },
                    "time2": {
                        "type": "string",
                        "description": "Second time string",
                    },
                    "tz2": {
                        "type": "string",
                        "description": "Timezone for second time",
                    },
                },
                "required": ["time1", "tz1", "time2", "tz2"],
            },
        ),
        Tool(
            name="search_holiday",
            description=(
                "Search for holidays by name. Returns holiday date and days until. "
                "If query is empty, returns next upcoming holiday."
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": (
                            "Search query for holiday names "
                            "(empty string returns next holiday)"
                        ),
                        "default": "",
                    },
                    "country": {
                        "type": "string",
                        "description": "ISO country code (e.g., 'US', 'GB', 'FR')",
                        "default": "",
                    },
                    "timezone": {
                        "type": "string",
                        "description": "Timezone to infer country from (e.g., 'America/New_York')",
                        "default": "",
                    },
                    "year": {
                        "type": "integer",
                        "description": "Year (default: current year)",
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Maximum number of results to return (default: 10)",
                        "default": 10,
                    },
                },
            },
        ),
        Tool(
            name="list_holidays",
            description="List all holidays for a specific country and year",
            inputSchema={
                "type": "object",
                "properties": {
                    "country": {
                        "type": "string",
                        "description": "ISO country code (e.g., 'US', 'GB', 'FR')",
                        "default": "",
                    },
                    "timezone": {
                        "type": "string",
                        "description": "Timezone to infer country from (e.g., 'America/New_York')",
                        "default": "",
                    },
                    "year": {
                        "type": "integer",
                        "description": "Year (default: current year)",
                    },
                },
            },
        ),
        # Chinese Calendar Tools
        Tool(
            name="gregorian_to_lunar",
            description="Convert Gregorian date to Chinese lunar date",
            inputSchema={
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "Gregorian date in YYYY-MM-DD format (default: today)",
                    }
                },
            },
        ),
        Tool(
            name="lunar_to_gregorian",
            description="Convert Chinese lunar date to Gregorian date",
            inputSchema={
                "type": "object",
                "properties": {
                    "lunar_year": {
                        "type": "integer",
                        "description": "Lunar year",
                    },
                    "lunar_month": {
                        "type": "integer",
                        "description": "Lunar month (1-12)",
                    },
                    "lunar_day": {
                        "type": "integer",
                        "description": "Lunar day (1-30)",
                    },
                    "is_leap_month": {
                        "type": "boolean",
                        "description": "Whether it's a leap month (default: false)",
                        "default": False,
                    },
                },
                "required": ["lunar_year", "lunar_month", "lunar_day"],
            },
        ),
        Tool(
            name="get_ganzhi",
            description="Get Heavenly Stems and Earthly Branches (Ganzhi/Four Pillars) for a date",
            inputSchema={
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "Date in YYYY-MM-DD format (default: today)",
                    }
                },
            },
        ),
        Tool(
            name="get_solar_terms",
            description="Get all 24 solar terms for a given year",
            inputSchema={
                "type": "object",
                "properties": {
                    "year": {
                        "type": "integer",
                        "description": "Year to get solar terms for (default: current year)",
                    }
                },
            },
        ),
        Tool(
            name="get_next_solar_term",
            description="Get the next solar term from a given date",
            inputSchema={
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "Starting date in YYYY-MM-DD format (default: today)",
                    }
                },
            },
        ),
        Tool(
            name="get_zodiac",
            description="Get Chinese zodiac animal for a given date or year",
            inputSchema={
                "type": "object",
                "properties": {
                    "date_or_year": {
                        "type": "string",
                        "description": "Date in YYYY-MM-DD format or year as string (default: current year)",
                    }
                },
            },
        ),
        Tool(
            name="get_chinese_holidays",
            description="Get Chinese traditional holidays for a given year",
            inputSchema={
                "type": "object",
                "properties": {
                    "year": {
                        "type": "integer",
                        "description": "Year to get Chinese holidays for (default: current year)",
                    }
                },
            },
        ),
        Tool(
            name="get_almanac_info",
            description="Get Chinese almanac information (suitable and unsuitable activities) for a date",
            inputSchema={
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "Date in YYYY-MM-DD format (default: today)",
                    }
                },
            },
        ),
        Tool(
            name="get_comprehensive_chinese_info",
            description="Get comprehensive Chinese calendar information for a given date",
            inputSchema={
                "type": "object",
                "properties": {
                    "date": {
                        "type": "string",
                        "description": "Date in YYYY-MM-DD format (default: today)",
                    }
                },
            },
        ),
    ]


@server.call_tool()
async def call_tool(name: str, arguments: dict) -> List[TextContent]:
    """Handle tool calls."""
    try:
        if name == "get_time":
            timezone = arguments.get("timezone")
            time_str = arguments.get("time_str")
            from_tz = arguments.get("from_tz")
            format_type = arguments.get("format", "iso")

            result = timemaster.get_time(
                timezone=timezone,
                time_str=time_str,
                from_tz=from_tz,
                format=format_type,
            )

            if time_str:
                actual_timezone = (
                    timezone if timezone else timemaster.get_local_timezone()
                )
                return [
                    TextContent(
                        type="text",
                        text=f"Converted time: {result} ({actual_timezone})",
                    )
                ]
            else:
                actual_timezone = (
                    timezone if timezone else timemaster.get_local_timezone()
                )
                return [
                    TextContent(
                        type="text",
                        text=f"Current time in {actual_timezone}: {result}",
                    )
                ]

        elif name == "get_local_timezone":
            local_tz = timemaster.get_local_timezone()
            return [
                TextContent(type="text", text=f"Local timezone: {local_tz}")
            ]

        elif name == "search_timezones":
            query = arguments.get("query", "")
            limit = arguments.get("limit", 20)
            matches = timemaster.find_timezones(query, limit=limit)
            if matches:
                result = "\n".join([f"- {tz}" for tz in matches])
                if query:
                    return [
                        TextContent(
                            type="text",
                            text=f"Matching timezones for '{query}':\n{result}",
                        )
                    ]
                else:
                    total_count = len(list(pytz.all_timezones))
                    suffix = (
                        f"\n... and {total_count - len(matches)} more"
                        if len(matches) < total_count
                        else ""
                    )
                    return [
                        TextContent(
                            type="text",
                            text=f"All timezones (showing {len(matches)}):\n{result}{suffix}",
                        )
                    ]
            else:
                return [
                    TextContent(
                        type="text",
                        text=f"No timezones found matching '{query}'",
                    )
                ]

        elif name == "calculate_time_difference":
            tz1 = arguments["tz1"]
            tz2 = arguments["tz2"]
            diff = timemaster.difference(tz1, tz2)
            return [
                TextContent(
                    type="text",
                    text=f"Time difference between {tz1} and {tz2}: {diff}",
                )
            ]

        elif name == "search_holiday":
            query = arguments.get("query", "")
            country = arguments.get("country", "")
            timezone = arguments.get("timezone", "")
            year = arguments.get("year")
            limit = arguments.get("limit", 10)

            result = timemaster.search_holiday(
                query=query,
                country=country if country else None,
                timezone=timezone if timezone else None,
                year=year,
                limit=limit,
            )
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "list_holidays":
            country = arguments.get("country", "")
            timezone = arguments.get("timezone", "")
            year = arguments.get("year")

            result = timemaster.list_holidays(
                country=country if country else None,
                timezone=timezone if timezone else None,
                year=year,
            )
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        # Chinese Calendar Tools
        elif name == "gregorian_to_lunar":
            date_str = arguments["date"]
            result = timemaster.gregorian_to_lunar(date_str)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "lunar_to_gregorian":
            year = arguments["year"]
            month = arguments["month"]
            day = arguments["day"]
            leap = arguments.get("leap", False)
            result = timemaster.lunar_to_gregorian(year, month, day, leap)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "get_ganzhi":
            date_str = arguments["date"]
            result = timemaster.get_ganzhi(date_str)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "get_solar_terms":
            year = arguments["year"]
            result = timemaster.get_solar_terms(year)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "get_zodiac":
            year = arguments["year"]
            result = timemaster.get_zodiac(year)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "get_chinese_holidays":
            year = arguments["year"]
            result = timemaster.get_chinese_holidays(year)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "get_almanac_info":
            date_str = arguments["date"]
            result = timemaster.get_almanac_info(date_str)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "is_chinese_holiday":
            date_str = arguments["date"]
            result = timemaster.is_chinese_holiday(date_str)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        elif name == "get_lunar_month_info":
            year = arguments["year"]
            month = arguments["month"]
            result = timemaster.get_lunar_month_info(year, month)
            return [
                TextContent(type="text", text=json.dumps(result, indent=2))
            ]

        else:
            return [TextContent(type="text", text=f"Unknown tool: {name}")]

    except Exception as e:
        return [
            TextContent(
                type="text",
                text=f"Error executing tool '{name}': {str(e)}",
            )
        ]


def setup_working_directory():
    """Automatically detect and set the correct working directory for time_master."""
    try:
        # Get the directory containing this file (src/)
        current_file_dir = Path(__file__).parent
        # Go up one level to get the timemaster package root
        timemaster_root = current_file_dir.parent

        # Change to the timemaster root directory
        os.chdir(timemaster_root)
        logger.info(f"Working directory set to: {timemaster_root}")

    except Exception as e:
        logger.warning(f"Could not set working directory automatically: {e}")
        logger.info("Continuing with current working directory")


async def main():
    """Main entry point for the MCP server."""
    # Automatically set up the working directory
    setup_working_directory()

    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream, write_stream, server.create_initialization_options()
        )


def async_main():
    """Async main entry point for script execution."""
    asyncio.run(main())


if __name__ == "__main__":
    asyncio.run(main())
